android:valueFrom
: slider 起始的數值android:valueTo
: slider 終點的數值android:stepSize
: 設置 Discrete slider 每個段落間距的數值
<!-- Continuous slider -->
<com.google.android.material.slider.Slider
...
android:valueFrom="0.0"
android:valueTo="100.0" />
<!-- Discrete slider -->
<com.google.android.material.slider.Slider
...
android:valueFrom="0.0"
android:valueTo="100.0"
android:stepSize="10.0" />
透過覆寫 SliderTouchListener 設置 slider touch 來監聽事件
continuousSlider.addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
override fun onStartTrackingTouch(slider: Slider) {
// 當用戶觸碰按壓時 ( ACTION_DOWN) 啟動
}
override fun onStopTrackingTouch(slider: Slider) {
// 當用戶觸碰離開螢幕時 ( ACTION_UP )觸發
}
})
continuousSlider.addOnChangeListener { slider, value, fromUser ->
// 監聽 slider 的 value 變化
continuousSliderValueTv.text = "Slider Value : $value"
}
discreteSlider.addOnChangeListener { slider, value, fromUser ->
// 監聽 slider 的 value 變化
discreteSliderValueTv.text = "Slider Value : $value"
}
與一般的 slider 差別在於設置 value 是給一個數值 array
<!-- Continuous Range slider -->
<com.google.android.material.slider.RangeSlider
android:id="@+id/continuous_range_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:valueFrom="0.0"
android:valueTo="100.0"
app:values="@array/ranger_slider" />
<!-- Discrete Ranger slider -->
<com.google.android.material.slider.RangeSlider
android:id="@+id/discrete_range_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:valueFrom="0.0"
android:stepSize="10"
android:valueTo="100.0"
app:values="@array/ranger_slider" />
給予兩個 item ,分別代表頭部與尾部的數值,若是給予多個 item,則會出現更多 thumb 讓用戶選取,但這樣的設計是應該要避免的,已經偏離 range 設計的樣貌
<array name="ranger_slider" >
<item>10</item>
<item>40</item>
</array>
設置監聽的方法與邏輯都大同小異,除了在設置 sliderTouchListener 要特別用 RangeSlier 的 listener
continuousRangeSlider.addOnSliderTouchListener(object :
RangeSlider.OnSliderTouchListener {
override fun onStartTrackingTouch(slider: RangeSlider) {
// 當用戶觸碰按壓時 ( ACTION_DOWN) 啟動
}
override fun onStopTrackingTouch(slider: RangeSlider) {
// 當用戶觸碰離開螢幕時 ( ACTION_UP )觸發
}
})
continuousRangeSlider.addOnChangeListener { slider, value, fromUser ->
continuousRangeSliderValueTv.text = " Con RangSlider Value : $value"
}
discreteRangeSlider.addOnChangeListener { slider, value, fromUser ->
discreteRangeSliderValueTv.text = "Dis RangerSlider Value : $value"
}
默認情況下,當 Slider 被選中時,它會在上方出現 value label。可以通過 app:labelBehavior
屬性或 setLabelBehavior
方法更改
app:labelBehavior
有下列幾個型態可選
在使用 slider 的情境上,通常會應用在給用戶選取特定的數值單位,若一次有多種 slider,只用 default 的樣式,沒辦法辨識之間的差異,那就必須去改動 slider 的 text label。使用 LabelFormatter,可以自行更換 Value Label 所選值的單位與大小(例如:1.5K、3M、12B)。通過 setLabelFormatter 方法來實現
rangeSlider.setLabelFormatter { value: Float ->
val format = NumberFormat.getCurrencyInstance()
format.maximumFractionDigits = 0
format.currency = Currency.getInstance("USD")
format.format(value.toDouble())
}
<com.google.android.material.slider.Slider
android:id="@+id/continuous_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:value="30.0"
android:valueFrom="0.0"
android:valueTo="100.0" />
<!-- Continuous Range slider -->
<com.google.android.material.slider.RangeSlider
android:id="@+id/continuous_range_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:valueFrom="0.0"
android:valueTo="100.0"
app:values="@array/ranger_slider" />
透過 android:stepSize
來設置
<!-- Discrete slider -->
<com.google.android.material.slider.Slider
...
android:stepSize="5.0" />
app:values="@array/ranger_slider
設置 ragnerandroid:stepSize="10"
設置 Discrete
<!-- Discrete Ranger slider -->
<com.google.android.material.slider.RangeSlider
...
android:stepSize="10"
app:values="@array/ranger_slider"
...
/>
1.Track
2.Thumb
3.Value label (optional)
4.Tick mark (discrete sliders)
Track 在 color 上有分為,激活與未激活的顏色差別,如果直接設置 app:trackColor
就會覆蓋這兩個屬性,所以如果要特別在這之間作區別的設計,記得要用 trackColorActive、trackColorInactive
Thumb 屬性中有 halo 這種東西可以調整,它是指在按壓 thumb 跑出類似 ripple 的效果
這邊還可以讓我們設置 radius、color。而 thumb 也能設置 stroke,預設上是沒有的
透過 app:labelBehavior
能更改 value label 的位置
Tick 在 color 上有分為,激活與未激活的顏色差別,如果直接設置 app:tickColor
就會覆蓋這兩個屬性,所以如果要特別在這之間作區別的設計,記得要用 tickColorActive、tickColorInactive
上方介紹完 Slider 所有組成與對應的屬性後,就可以依照剛剛所介紹的過 attributes 去做修改。這邊再重新複習一下 Track , Thumb , halo 在顏色上是吃 colorPrimary,tick 在激活時是吃 colorOnPrimay 未激活則是 colorPrimay
<style name="ThemeOverlay.App.Slider" parent="">
<item name="colorPrimary">@color/lightGreen</item>
<item name="colorOnPrimary">@color/darkGreen</item>
</style>
而這邊比較特別的是 Value label,預設上系統是直接設定一個 @style/Widget.MaterialComponents.Tooltip
,如果我們想改動 Value label 的顏色,就要去覆寫它
先看一下這個 Tooltip 裡面有些什麼,預設上設置了 textColor 吃的是 colorOnPrimary。也代表我們想去改動 Value label 的文字顏色,就要去覆蓋它的預設,不然就會隨著 theme colorOnPrimary 改變
<style name="TextAppearance.MaterialComponents.Tooltip" parent="TextAppearance.MaterialComponents.Body2">
<item name="android:textColor">?attr/colorOnPrimary</item>
這邊改動一下字型與背景顏色,設置 textAppearance、backgroundTint、textColor
<style name="Widget.App.Tooltip" parent="Widget.MaterialComponents.Tooltip">
<item name="android:textAppearance">@style/TextAppearance.App.Tooltip</item>
<item name="backgroundTint">@color/lightGreen</item>
<item name="android:textColor">@color/lightBlue</item>
</style>
<style name="TextAppearance.App.Tooltip" parent="TextAppearance.MaterialComponents.Tooltip">
<item name="fontFamily">@font/amiko_semibold</item>
<item name="android:fontFamily">@font/amiko_semibold</item>
</style>
最後包成一個新的 Slider style
<style name="Widget.App.Slider" parent="Widget.MaterialComponents.Slider">
<item name="materialThemeOverlay">@style/ThemeOverlay.App.Slider</item>
<item name="labelStyle">@style/Widget.App.Tooltip</item>
</style>
雖然 Slider 是一個小型元件,設置起來非常容易,但內部的組件卻被 Material Design 劃分得很細部,在元件的屬性上就變得非常多元,也讓開發者需要去花費大量時間閱讀文件並理解,但這前提是沒有用 style 去設置。如果自行去修改每個屬性當然非常耗費時間,這也是 Material Design 想要解決的問題,透過統一規範的格式與設定,讓開發者能透過 theme、style 來快速改變造型,希望大家都能養成寫好 style 的習慣
若對實作還是有點不懂的,這邊提供我的 Github 方便大家參考